package com.alibaba.citrus.cr.platform.enhance.facade.service.scitem;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crplatformenhance.model.dto.ScItemMultipleExcludeCheckConfigBatchDeleteRequest;
import com.epoch.app.crplatformenhance.model.dto.ScItemMultipleExcludeCheckConfigCreateRequest;
import com.epoch.app.crplatformenhance.model.dto.ScItemMultipleExcludeCheckConfigDeleteRequest;
import com.epoch.app.crplatformenhance.model.dto.ScItemMultipleExcludeCheckConfigLoadListRequest;
import com.epoch.app.crplatformenhance.model.dto.ScItemMultipleExcludeCheckConfigUpdateRequest;
import com.epoch.app.crplatformenhance.model.enums.AllocateApplyType;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.dto.CreateResponse;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.dto.DeleteRequest;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.dto.DeleteResponse;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.dto.LoadRequest;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.model.ScItemMultipleExcludeCheckConfig;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfig.service.ScItemMultipleExcludeCheckConfigService;
import com.epoch.app.crplatformenhance.scitemmultipleexcludecheckconfigwrite.service.ScItemMultipleExcludeCheckConfigWriteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @description: 配置排除货品倍数校验 写服务
 * @author: yuhw
 * @date: 2023年04月17日 16:53
 **/
@Component
@Primary
public class ScItemMultipleExcludeCheckConfigWriteServiceImpl implements ScItemMultipleExcludeCheckConfigWriteService {

    private static Log log = Log.getLogger(ScItemMultipleExcludeCheckConfigWriteServiceImpl.class);

    @Resource
    private ScItemMultipleExcludeCheckConfigService excludeCheckConfigService;

    /**
     * 创建排除货品倍数校验配置
     * @param createRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Long> create(ScItemMultipleExcludeCheckConfigCreateRequest createRequest) {
        //校验新增请求参数
        checkCreateRequest(createRequest);
        //校验新增唯一键是否冲突: 提报组织id + 逻辑仓库id + 调拨预报类型
        checkDuplicate(createRequest.getOrganizationId(),createRequest.getShipWarehouseAreaId(),createRequest.getAllocateApplyType(),null);
        //组装创建模型参数 创建排除货品倍数校验的配置记录
        CreateResponse createResponse = excludeCheckConfigService.create(buildExcludeCheckConfig(createRequest));
        if (createResponse.getLastInsertId() == null){
            throw new FacadeException("OTS-01-005-02-15-024");
        }
        return Result.success(createResponse.getLastInsertId());
    }

    /**
     * 更新排除货品校验配置
     * @param updateRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Long> update(ScItemMultipleExcludeCheckConfigUpdateRequest updateRequest) {
        //校验更新请求参数
        checkUpdateRequest(updateRequest);
        //校验更新记录数据库是否存在
        checkExist(updateRequest.getId());
        //校验唯一键是否冲突 提报组织id + 逻辑仓库id + 调拨预报类型
        checkDuplicate(updateRequest.getOrganizationId(),updateRequest.getShipWarehouseAreaId(),updateRequest.getAllocateApplyType(),updateRequest.getId());
        //更新排除货品校验配置
        excludeCheckConfigService.update(buildExcludeCheckConfig(updateRequest));
        return Result.success(Long.parseLong(updateRequest.getId()));
    }

    /**
     * 根据主键id删除排除货品校验配置
     * @param configDeleteRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> delete(ScItemMultipleExcludeCheckConfigDeleteRequest configDeleteRequest) {
        //校验入参删除id
        if (configDeleteRequest == null || configDeleteRequest.getId() == null){
            throw new FacadeException("OTS-01-005-02-15-025");
        }
        DeleteRequest deleteRequest = new DeleteRequest();
        deleteRequest.setId(configDeleteRequest.getId());
        try{
            DeleteResponse deleteResponse = excludeCheckConfigService.delete(deleteRequest);
            if (deleteResponse == null || deleteResponse.getCount() == null || deleteResponse.getCount() < 1){
                throw new FacadeException("OTS-01-005-02-15-029");
            }
        }catch (Throwable e){
            log.error("ScItemMultipleExcludeCheckConfig_delete,request:{}", JSON.toJSONString(configDeleteRequest),e);
            throw new FacadeException("OTS-01-005-02-15-029");
        }
        return Result.success(true);
    }

    /**
     * 批量删除 根据主键id集合排除货品校验配置
     * @param batchDeleteRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots")
    public Result<Boolean> batchDelete(ScItemMultipleExcludeCheckConfigBatchDeleteRequest batchDeleteRequest) {
        //校验批量删除id列表
        if (batchDeleteRequest == null || CollectionUtils.isEmpty(batchDeleteRequest.getIds())){
            throw new FacadeException("OTS-01-005-02-15-028");
        }
        //循环删除配置
        batchDeleteRequest.getIds().forEach(id->{
            ScItemMultipleExcludeCheckConfigDeleteRequest deleteRequest = new ScItemMultipleExcludeCheckConfigDeleteRequest();
            deleteRequest.setId(id);
            delete(deleteRequest);
        });
        return Result.success(true);
    }

    //校验创建参数
    private void checkCreateRequest(ScItemMultipleExcludeCheckConfigCreateRequest createRequest){
        validParams(createRequest.getOrganizationId(), createRequest.getShipWarehouseAreaId(), createRequest.getAllocateApplyType());
    }

    //校验更新参数
    private void checkUpdateRequest(ScItemMultipleExcludeCheckConfigUpdateRequest updateRequest){
        //更新请求主键id不能为空
        if (updateRequest == null || StringUtils.isBlank(updateRequest.getId())){
            throw new FacadeException("OTS-01-005-02-15-025");
        }
        validParams(updateRequest.getOrganizationId(), updateRequest.getShipWarehouseAreaId(), updateRequest.getAllocateApplyType());
    }

    /**
     * 校验 提报组织id 发货逻辑仓id 调拨预报类型入参
     * @param organizationId 提报组织id
     * @param shipWarehouseAreaId 发货逻辑仓id
     * @param allocateApplyType 调拨预报类型 1:计划调拨 2:总部销售调拨 5:工厂直发
     */
    private void validParams(String organizationId, String shipWarehouseAreaId, String allocateApplyType) {
        // 提报组织id 发货逻辑仓id 调拨预报类型 非空
        if (StringUtils.isBlank(organizationId)){
            throw new FacadeException("OTS-01-005-02-15-020");
        }
        if (StringUtils.isBlank(shipWarehouseAreaId)){
            throw new FacadeException("OTS-01-005-02-15-021");
        }
        if (StringUtils.isBlank(allocateApplyType)){
            throw new FacadeException("OTS-01-005-02-15-022");
        }
        //调拨预报类型合法
        if (AllocateApplyType.of(allocateApplyType) == null){
            throw new FacadeException("OTS-01-005-02-15-026");
        }
    }

    //根据主键id 判断配置是否存在
    private void checkExist(String id){
        LoadRequest loadRequest = new LoadRequest();
        loadRequest.setId(Long.parseLong(id));
        ScItemMultipleExcludeCheckConfig load = excludeCheckConfigService.load(loadRequest);
        if (load == null){
            throw new FacadeException("OTS-01-005-02-15-027");
        }
    }

    //根据提报组织id + 发货逻辑仓id + 调拨预报类型  + (主键id) 判断是否冲突
    private void checkDuplicate(String organizationId,String shipWarehouseAreaId,String allocateApplyType,String id){
        ScItemMultipleExcludeCheckConfigLoadListRequest loadListRequest = new ScItemMultipleExcludeCheckConfigLoadListRequest();
        loadListRequest.setOrganizationId(organizationId);
        loadListRequest.setShipWarehouseAreaId(shipWarehouseAreaId);
        loadListRequest.setAllocateApplyType(allocateApplyType);
        Result<List<ScItemMultipleExcludeCheckConfig>> listResult = excludeCheckConfigService.loadList(loadListRequest);
        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
            //更新配置时允许数据库存在相同唯一键.  新增时不允许
            if (StringUtils.isBlank(id) || !Objects.equals(id, listResult.getResult().get(0).getId().toString())) {
                throw new FacadeException("OTS-01-005-02-15-023");
            }
        }
    }
    //根据创建请求生成模型
    private ScItemMultipleExcludeCheckConfig buildExcludeCheckConfig(ScItemMultipleExcludeCheckConfigCreateRequest createRequest){
        ScItemMultipleExcludeCheckConfig config = new ScItemMultipleExcludeCheckConfig();
        //参数赋值
        fillExcludeCheckConfig(createRequest, config);
        return config;
    }

    //参数赋值
    private void fillExcludeCheckConfig(ScItemMultipleExcludeCheckConfigCreateRequest createRequest, ScItemMultipleExcludeCheckConfig config) {
        //构建排除校验配置模型
        buildConfig(config, createRequest.getOrganizationId(), createRequest.getOrganizationCode(), createRequest.getOrganizationName(),
                createRequest.getShipWarehouseAreaId(), createRequest.getShipWarehouseAreaName(), createRequest.getShipWarehouseAreaCode(),
                createRequest.getAllocateApplyType());
    }

    /**
     * 排除校验配置模型属性赋值
     * @param config 排除货品校验配置模型
     * @param organizationId 提报组织id
     * @param organizationCode 提报组织编码
     * @param organizationName 提报组织名称
     * @param shipWarehouseAreaId 发货逻辑仓id
     * @param shipWarehouseAreaName 发货逻辑仓名称
     * @param shipWarehouseAreaCode 发货逻辑仓编码
     * @param allocateApplyType  调拨预报类型 1:计划调拨 2:总部销售调拨 5:工厂直发
     */
    private void buildConfig(ScItemMultipleExcludeCheckConfig config, String organizationId, String organizationCode, String organizationName, String shipWarehouseAreaId, String shipWarehouseAreaName, String shipWarehouseAreaCode, String allocateApplyType) {
        config.setOrganizationId(organizationId);
        config.setOrganizationCode(organizationCode);
        config.setOrganizationName(organizationName);
        config.setShipWarehouseAreaId(shipWarehouseAreaId);
        config.setShipWarehouseAreaName(shipWarehouseAreaName);
        config.setShipWarehouseAreaCode(shipWarehouseAreaCode);
        config.setAllocateApplyType(allocateApplyType);
        config.setAllocateApplyTypeDesc(Optional.ofNullable(AllocateApplyType.of(allocateApplyType))
                .map(AllocateApplyType::getDesc).orElse(null));
    }

    //构建更新排除货品倍数校验配置
    private ScItemMultipleExcludeCheckConfig buildExcludeCheckConfig(ScItemMultipleExcludeCheckConfigUpdateRequest updateRequest){
        ScItemMultipleExcludeCheckConfig config = new ScItemMultipleExcludeCheckConfig();
        config.setId(Long.parseLong(updateRequest.getId()));
        buildConfig(config, updateRequest.getOrganizationId(), updateRequest.getOrganizationCode(), updateRequest.getOrganizationName(),
                updateRequest.getShipWarehouseAreaId(), updateRequest.getShipWarehouseAreaName(), updateRequest.getShipWarehouseAreaCode(), updateRequest.getAllocateApplyType());
        return config;
    }
}
